package io.itit.ecp.admin.provide.action.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import icu.mhb.mybatisplus.plugln.core.JoinLambdaWrapper;
import icu.mhb.mybatisplus.plugln.extend.Joins;
import io.itit.ecp.admin.provide.action.req.MeterDeviceQueryReq;
import io.itit.ecp.admin.provide.action.resp.DeviceMeterStaticsRes;
import io.itit.ecp.admin.provide.helper.SceneHelper;
import io.itit.ecp.admin.server.entity.*;
import io.itit.ecp.admin.server.service.IPhysicalModelService;
import io.itit.grass.common.provide.action.resp.ResultResp;
import io.itit.grass.common.provide.action.validation.IQueryPage;
import io.itit.grass.estelle.starter.core.ExcelXSSFUtil;
import io.itit.grass.estelle.starter.util.JsonUtil;
import io.itit.grass.web.wall.utils.PageUtils;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * 设备计量统计
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/ecp-admin/deviceMeterStatics")
public class DeviceMeterStaticsController {

    @Resource
    private IPhysicalModelService physicalModelService;

    @RequestMapping("queryPage")
    public ResultResp<IPage<DeviceMeterStaticsRes>> page(@RequestBody @Validated(IQueryPage.class) MeterDeviceQueryReq req) {
        Page<DeviceMeterStaticsRes> page = buildQW(req).joinPage(PageUtils.getPage(req, DeviceMeterStaticsRes.class), DeviceMeterStaticsRes.class);
        setValues(page.getRecords());
        return ResultResp.success(SceneHelper.i().setSceneInfo(page));
    }

    private void setValues(List<DeviceMeterStaticsRes> list) {
        Set<String> modelIds = list.stream()
                .map(DeviceMeterStaticsRes::getModelId)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toSet());
        Map<String, PhysicalModelEntity> physicalModelMap = new HashMap<>();
        if (!modelIds.isEmpty()) {
            physicalModelMap = physicalModelService.listByIds(modelIds).stream().collect(Collectors.toMap(PhysicalModelEntity::getId, Function.identity()));
        }
        for (DeviceMeterStaticsRes item : list) {
            if (StringUtils.isNotEmpty(item.getModelId())) {
                PhysicalModelEntity physicalModel = physicalModelMap.get(item.getModelId());
                if (Objects.nonNull(physicalModel)) {
                    String dataExt = physicalModel.getDataExt();
                    if (StringUtils.isNotEmpty(dataExt) && JSON.isValidObject(dataExt)) {
                        item.setUnit(JSON.parseObject(dataExt).getString("unit"));
                    }
                }
            }
        }
    }

    @ApiOperation("导出")
    @PostMapping("export")
    public void export(@RequestBody MeterDeviceQueryReq req, HttpServletResponse response) {
        List<DeviceMeterStaticsRes> respList = SceneHelper.i().setSceneInfo(buildQW(req).joinList(DeviceMeterStaticsRes.class));
        setValues(respList);
        ExcelXSSFUtil.export("deviceMeterStaticsExport", JsonUtil.toJson(respList), response);
    }


    private static JoinLambdaWrapper<MeterDeviceEntity> buildQW(MeterDeviceQueryReq req) {
        return Joins.of(MeterDeviceEntity.class)
                .leftJoin(SceneProjectEntity.class, SceneProjectEntity::getId, MeterDeviceEntity::getSceneProjectId)
                .selectAs(SceneProjectEntity::getProjectName, DeviceMeterStaticsRes::getSceneProjectName)
                .end()
                .leftJoin(EnergyConsumptionTypeEntity.class, EnergyConsumptionTypeEntity::getId, MeterDeviceEntity::getEnergyTypeId)
                .selectAs(EnergyConsumptionTypeEntity::getEnergyName, DeviceMeterStaticsRes::getEnergyTypeName)
                .end()
                .and(StringUtils.isNotEmpty(req.getDeviceCodeOrName()), t ->
                        t.like(MeterDeviceEntity::getDeviceCode, req.getDeviceCodeOrName())
                                .or()
                                .like(MeterDeviceEntity::getDeviceName, req.getDeviceCodeOrName()))
                .eq(StringUtils.isNotEmpty(req.getDeviceType()), MeterDeviceEntity::getDeviceType, req.getDeviceType())
                .in(CollectionUtils.isNotEmpty(req.getDeviceTypeList()), MeterDeviceEntity::getDeviceType, req.getDeviceTypeList())
                .eq(StringUtils.isNotEmpty(req.getDeviceStatus()), MeterDeviceEntity::getDeviceStatus, req.getDeviceStatus())
                .in(CollectionUtils.isNotEmpty(req.getDeviceStatusList()), MeterDeviceEntity::getDeviceStatus, req.getDeviceStatusList())
                .eq(StringUtils.isNotEmpty(req.getMeterType()), MeterDeviceEntity::getMeterType, req.getMeterType())
                .in(CollectionUtils.isNotEmpty(req.getMeterTypeList()), MeterDeviceEntity::getMeterType, req.getMeterTypeList())
                .eq(StringUtils.isNotEmpty(req.getSceneProjectId()), MeterDeviceEntity::getSceneProjectId, req.getSceneProjectId())
                .eq(StringUtils.isNotEmpty(req.getSceneEdificeId()), MeterDeviceEntity::getSceneEdificeId, req.getSceneEdificeId())
                .eq(StringUtils.isNotEmpty(req.getSceneFloorId()), MeterDeviceEntity::getSceneFloorId, req.getSceneFloorId())
                .eq(StringUtils.isNotEmpty(req.getSceneRoomId()), MeterDeviceEntity::getSceneRoomId, req.getSceneRoomId())
                .eq(StringUtils.isNotEmpty(req.getReadMeterType()), MeterDeviceEntity::getReadMeterType, req.getReadMeterType())
                .in(CollectionUtils.isNotEmpty(req.getReadMeterTypeList()), MeterDeviceEntity::getReadMeterType, req.getReadMeterTypeList())
                .eq(StringUtils.isNotEmpty(req.getEnergyTypeId()), MeterDeviceEntity::getEnergyTypeId, req.getEnergyTypeId())
                .eq(StringUtils.isNotEmpty(req.getReadMeterTag()), MeterDeviceEntity::getReadMeterTag, req.getReadMeterTag())
                .in(CollectionUtils.isNotEmpty(req.getReadMeterTagList()), MeterDeviceEntity::getReadMeterTag, req.getReadMeterTagList())
                .eq(StringUtils.isNotEmpty(req.getPurpose()), MeterDeviceEntity::getPurpose, req.getPurpose())
                .eq(StringUtils.isNotEmpty(req.getStatus()), MeterDeviceEntity::getStatus, req.getStatus())
                .in(CollectionUtils.isNotEmpty(req.getStatusList()), MeterDeviceEntity::getStatus, req.getStatusList())
                .eq(StringUtils.isNotEmpty(req.getDelFlag()), MeterDeviceEntity::getDelFlag, req.getDelFlag())
                .in(CollectionUtils.isNotEmpty(req.getDelFlagList()), MeterDeviceEntity::getDelFlag, req.getDelFlagList())
                .eq(StringUtils.isNotEmpty(req.getDeptId()), MeterDeviceEntity::getDeptId, req.getDeptId())
                .gt(StringUtils.isNotEmpty(req.getStartTime()), MeterDeviceEntity::getCreateTm, req.getStartTime())
                .lt(StringUtils.isNotEmpty(req.getEndTime()), MeterDeviceEntity::getCreateTm, req.getEndTime())
                .in(CollectionUtils.isNotEmpty(req.getIds()), MeterDeviceEntity::getId, req.getIds())
                .last(StringUtils.isNotEmpty(req.getSortColumn()), PageUtils.lastOrderBy(req))
                .orderByDesc(StringUtils.isEmpty(req.getSortColumn()), MeterDeviceEntity::getCreateTm);
    }
}
